#!/usr/bin/env perl
#
# Copyright (c) 2012-2013 Jeffrey M. Squyres.  All rights reserved.
#
# $COPYRIGHT$
# 
# Additional copyrights may follow
# 
# $HEADER$
#
# This module required me to "aptitute install libwww-perl" on my
# Raspberry Pi.
#

package RubySlippers::Action::Pushover;

use strict;
use RubySlippers::Messages;
use RubySlippers::Globals;
use RubySlippers::Config;

use LWP::UserAgent;

# Current state (last message we sent to pushover)
my $_current_state;

# Pushover user and app tokens
my $_pushover_user;
my $_pushover_app;

# (Optional) Pushover alert sound
my $_pushover_sound;

#
# Send the message to pushover
#
sub _pushover {
    my $msg = shift;

    my $args = [
        timestamp => time(),
        token => $_pushover_app,
        user => $_pushover_user,
        message => $msg,
        ];

    # Add the sound, if specified
    if (length($_pushover_sound) > 0) {
        push(@{$args}, "sound");
        push(@{$args}, $_pushover_sound);
    }

    # Send the message to Pushover
    LWP::UserAgent->new()->post(
        "https://api.pushover.net/1/messages.json", $args);
}

#
# This function will be called by the Action engine with a state of
# HOME, NOT_HOME, or UNKNOWN.
#
sub _pushover_act {
    my $new_state = shift;
    my $reason = shift;

    if (STATE_HOME != $new_state && STATE_NOT_HOME != $new_state) {
        Verbose("Pushover: Got UNKNOWN state; not doing anything ($reason)");
        return;
    }

    if ($new_state == $_current_state) {
	Verbose("New state same as old state; not doing anything ($reason)");
        return;
    }

    if (STATE_HOME == $new_state) {
        Verbose("Pushover: Setting HOME: $reason");
        _pushover("Setting HOME: $reason");

    } elsif (STATE_NOT_HOME == $new_state) {
        Verbose("Pushover: Setting AWAY: $reason\n");
        _pushover("Setting AWAY: $reason");
    }

    $_current_state = $new_state;
}

#
# Trivial masking
#
sub _mask {
    my $str = shift;
    return "..." . substr($str, length($str) - 4);
}

sub _trim {
    my $str = shift;
    $str =~ s/^\s*(.*?)\s*$/\1/;
    return $str;
}

#
# Open the module.  We qualify to return a module if we find pushover.py
# in the path and also find a pushover_username and pushover_password in the
# config.
#
sub open {
    $_pushover_user = RubySlippers::Config::get("pushover_user");
    $_pushover_app = RubySlippers::Config::get("pushover_app");
    $_pushover_sound = RubySlippers::Config::get("pushover_sound");

    if ((defined($_pushover_user) && !defined($_pushover_app)) ||
        (!defined($_pushover_user) && defined($_pushover_app))) {
        Warning("If either of pushover_user or pushover_app are defined, they must both be defined.  Skipping the Pushover module.");
        return undef;
    }
    if (!defined($_pushover_user) && !defined($_pushover_app)) {
        Warning("Did not find either pushover_user or pushover_app; skipping the Pushover module");
        return undef;
    }

    # Log that we're starting up.  Helps to know if there was a power
    # outage, or somesuch.
    _pushover("Starting up");

    # Mask the user and app so that we can display them in the syslog/etc.
    my $masked_user = _mask($_pushover_user);
    my $masked_app = _mask($_pushover_app);

    Verbose("Pushover returning Action module");
    Verbose("    Pushover user:  $masked_user");
    Verbose("    Pushover app:   $masked_app");
    Verbose("  Pushover sound:   $_pushover_sound");

    my @ret;
    push(@ret, {
        act => \&_pushover_act,
        name => "Pushover action",
         });
    return \@ret;
}

1;
